/*
 * @Author: 晴鸢. 3013433857@qq.com
 * @Date: 2025-11-05 08:11:27
 * @LastEditors: 晴鸢. 3013433857@qq.com
 * @LastEditTime: 2025-11-05 09:01:11
 * @FilePath: /Learn/Webself/Log.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once
#include <iostream>
#include <stdarg.h> //可变参数
#include <time.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/stat.h>
#include <fcntl.h>

#define Info 0
#define Debug 1
#define Warning 2
#define Error 3
#define Fatal 4

#define Screen    1
#define Onefile   2
#define Classfile 3
#define SIZE 1024

#define LogFile "log.txt"
class  Log
{
public:
    Log()
    {
        printMethod=Screen;
        path="./log/";
    }
    void Enable(int method)
    {
        printMethod=method;
    }

    std::string levelToString(int level)
    {
        switch (level)
        {
        case Info:
            return "Info";
        case Debug:
            return "Debug";
        case Warning:
            return "Warning";
        case Error:
            return "Error";
        case Fatal:
            return "Fatal";
        default:
            return "Node";
        }
    }

    void operator()(int level, const char *format, ...)
    {
        time_t t = time(nullptr);
        struct tm *ctime = localtime(&t);
        char leftbuffer[SIZE];
        // 处理日期和格式问题
        snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(),
                 ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
                 ctime->tm_hour, ctime->tm_min, ctime->tm_sec);

        va_list s;
        va_start(s, format);
        char rightbuffer[SIZE];
        // 将格式化数据写入字符数组（缓冲区）并限制最大长度以避免溢出(接收的是已通过 va_start 初始化的 va_list 类型参数)
        vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
        va_end(s);

        char logtxt[SIZE * 2];
        // snprintf将格式化的数据（如数字、字符串等）写入指定字符数组（缓冲区）
        snprintf(logtxt, sizeof(logtxt), "%s %s", leftbuffer, rightbuffer);
        printLog(level,logtxt);
    }
    //...为可变参数
    void logmessage(int level, const char *format, ...) // format为格式化字符串
    {
        time_t t = time(nullptr);
        struct tm *ctime = localtime(&t);
        char leftbuffer[SIZE];
        // 处理日期和格式问题
        snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(),
                 ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
                 ctime->tm_hour, ctime->tm_min, ctime->tm_sec);

        va_list s;
        va_start(s, format);
        char rightbuffer[SIZE];
        // 将格式化数据写入字符数组（缓冲区）并限制最大长度以避免溢出(接收的是已通过 va_start 初始化的 va_list 类型参数)
        vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
        va_end(s);

        char logtxt[SIZE * 2];
        // snprintf将格式化的数据（如数字、字符串等）写入指定字符数组（缓冲区）
        snprintf(logtxt, sizeof(logtxt), "%s %s", leftbuffer, rightbuffer);
        printLog(level,logtxt);
        //printf("%s", logtxt);

        // time_t t=time(nullptr);//获取时间戳
        // struct tm* ctime=localtime(&t); //struct tm* 是储存大量与时间相关的信息的数据结构
        // 年份从1900年开始，月份从0月开始
        // printf("%d-%d-%d %d:%d:%d\n",ctime->tm_year+1900,ctime->tm_mon+1,
        //       ctime->tm_mday,ctime->tm_hour,ctime->tm_min,ctime->tm_sec);
    }

    void printLog(int level,const std::string& logtxt)
    {
        switch(printMethod)
        {
            case Screen:
                std::cout<<logtxt<<std::endl;
            break;
            case Onefile:
                printOneFile(LogFile,logtxt);
            break;
            case Classfile:
                printClassFile(level,logtxt);
            break;
            default:
            break;
        }
    }

    void printOneFile(const std::string&logname,const std::string&logtxt)
    {
        std::string _logname=path+logname;
        int fd=open(_logname.c_str(),O_WRONLY|O_CREAT|O_APPEND,0666);//文件名"log.txt"
        if(fd<0) 
        {
            perror("Logopen error:");
            return;
        }
        write(fd,logtxt.c_str(),logtxt.size());
        close(fd);
    }

    void  printClassFile(int level,const std::string&logtxt)
    {
        std::string filename=LogFile;
        filename+='.';
        filename+=levelToString(level);//文件名"log.txt.Debug/Warning/Fatal"
        printOneFile(filename,logtxt);
    }
    ~Log(){}
    
private:
    int printMethod;
    std::string path;
};

// 以下只是为可变参数的示范
int sum(int n, ...)
{
    va_list s;      // 相当于char*类型的结构
    va_start(s, n); // 使s找到可变参数的起始地址
    int sum = 0;
    while (n)
    {
        sum += va_arg(s, int); // 从可变参数列表中取出当前参数，并让s自动指向 “下一个参数”
        n--;
    }
    va_end(s); // s=NULL 使用完后需要清理
    return sum;
}
Log lg;